<script setup lang="ts">
import { ref, watch, nextTick, computed, onUnmounted } from 'vue';
import type { PropType } from 'vue';
import { getImgUrl } from "#/utils/getImgUrl"

defineOptions({ name: 'BannerPreview' });

// 定义文案配置类型
interface TextConfig {
  id: string;
  desc: string;
  x: number;
  y: number;
  textFormatConfigs?: {
    alignCenter?: string;
    fontBold?: boolean;
    fontColor?: string;
    fontSize?: number;
    italic?: boolean;
    underline?: boolean;
    fontFamily?: string;
    textAlign?: string;
    textWidth?: number;
    textHeight?: number;
  };
}

const props = defineProps({
  banner: {
    type: Object as PropType<any>,
    required: true,
  },
  edit: {
    type: Boolean,
    default: false,
  },
});

const emit = defineEmits(['update:banner']);
const canvasRef = ref<HTMLCanvasElement | null>(null);
const imgLoading = ref(false);
const imgLoaded = ref(false);
const backgroundImage = ref<HTMLImageElement | null>(null);

// 拖拽相关状态
const isDragging = ref(false);
const draggedTextId = ref<string | null>(null);
const dragStartPos = ref({ x: 0, y: 0 });
const canvasRect = ref({ width: 0, height: 0 });
const textBlocks = ref<TextConfig[]>([]);

// 悬浮状态
const hoveredTextId = ref<string | null>(null);

// 宽高拖拽状态
const isResizing = ref(false);
const resizingTextId = ref<string | null>(null);
const resizeStartPos = ref({ x: 0, y: 0 });
const resizeStartSize = ref({ width: 0, height: 0 });

// 对齐线相关
const showCenterLines = ref(false);
const showAlignmentLines = ref(false);
const alignmentLine = ref({ x: 0, y: 0, type: '' }); // type: 'vertical' | 'horizontal'

// 计算canvas中心线
const centerLines = computed(() => {
  if (!canvasRect.value.width || !canvasRect.value.height) return { x: 0, y: 0 };
  return {
    x: canvasRect.value.width / 2,
    y: canvasRect.value.height / 2
  };
});

// 检测是否靠近中心线
function isNearCenterLine(x: number, y: number, threshold: number = 5) {
  const center = centerLines.value;
  return {
    nearVertical: Math.abs(x - center.x) < threshold,
    nearHorizontal: Math.abs(y - center.y) < threshold
  };
}

// 检测是否与其他文案区块对齐
function findAlignmentLines(currentX: number, currentY: number, currentId: string) {
  const threshold = 5;
  const lines: { x: number, y: number, type: string }[] = [];

  textBlocks.value.forEach(text => {
    if (text.id === currentId) return;

    // 垂直对齐
    if (Math.abs(currentX - text.x) < threshold) {
      lines.push({ x: text.x, y: 0, type: 'vertical' });
    }

    // 水平对齐
    if (Math.abs(currentY - text.y) < threshold) {
      lines.push({ x: 0, y: text.y, type: 'horizontal' });
    }
  });

  return lines.length > 0 ? lines[0] : null;
}

// 吸附到对齐线
function snapToAlignment(x: number, y: number, alignmentLine: any) {
  if (!alignmentLine) return { x, y };

  if (alignmentLine.type === 'vertical') {
    return { x: alignmentLine.x, y };
  } else if (alignmentLine.type === 'horizontal') {
    return { x, y: alignmentLine.y };
  }

  return { x, y };
}

function arrayBufferToImageBase64(buffer: ArrayBuffer, mimeType: string = 'image/png'): string {
  const bytes = new Uint8Array(buffer)
  let binary = '';
  bytes.forEach(byte => binary += String.fromCharCode(byte))
  return `data:${mimeType};base64,${btoa(binary)}`
}

async function loadImage(url: string) {
  try {
    imgLoading.value = true
    const src = await getImgUrl(url) as any
    const base64Content = arrayBufferToImageBase64(src)
    const img = new Image()
    img.src = base64Content
    img.crossOrigin = 'anonymous'
    img.onload = () => {
      backgroundImage.value = img
      imgLoaded.value = true
      imgLoading.value = false
      nextTick(() => {
        drawCanvas()
      })
    };
    img.onerror = () => {
      imgLoaded.value = false
      imgLoading.value = false
    };
  } catch (error) {
    imgLoading.value = false
  }
}

// 绘制文案区块
function drawTextBlocks(ctx: CanvasRenderingContext2D) {
  textBlocks.value.forEach(text => {
    const config = text.textFormatConfigs || {};
    const fontSize = config.fontSize || 16;
    const textWidth = config.textWidth === 0 ? canvasRect.value.width / 2 : (config.textWidth || 200); // textWidth为0时使用canvas宽度
    // 设置文字样式
    ctx.font = `${config.fontBold ? 'bold' : 'normal'} ${config.italic ? 'italic' : 'normal'} ${fontSize}px ${config.fontFamily || 'Arial'}`;
    ctx.fillStyle = config.fontColor || '#000000';
    
    // 根据alignCenter设置对齐方式
    let textAlign: CanvasTextAlign = config.alignCenter as CanvasTextAlign || 'left';
    ctx.textAlign = textAlign;
    ctx.textBaseline = 'top';
    
    // 文字换行处理
    const textHeight = config.textHeight === 0 ? (fontSize + 8) * 2 : (config.textHeight || (fontSize + 8) * 2);
    const lineHeight = fontSize + 8;
    const maxLines = Math.floor(textHeight / lineHeight);
    
    // 按字符分割文字
    const chars = text.desc.split('');
    const lines: string[] = [];
    let currentLine = '';
    
    // 逐字符处理换行
    for (let i = 0; i < chars.length; i++) {
      const char = chars[i];
      if (!char) continue;
      
      const testLine = currentLine + char;
      const testWidth = ctx.measureText(testLine).width;
      
      if (testWidth > textWidth) {
        if (currentLine) {
          lines.push(currentLine);
          currentLine = char;
        } else {
          // 单个字符就超过宽度，强制换行
          lines.push(char);
        }
      } else {
        currentLine = testLine;
      }
    }
    
    // 添加最后一行
    if (currentLine) {
      lines.push(currentLine);
    }
    
    // 限制行数
    const displayLines = lines.slice(0, maxLines);
    
    // 绘制换行文字
    displayLines.forEach((line, index) => {
      let lineDrawX = text.x;
      if (textAlign === 'center') {
        lineDrawX = text.x + textWidth / 2;
      } else if (textAlign === 'right') {
        lineDrawX = text.x + textWidth;
      }
      
      const lineY = text.y + index * lineHeight;
      ctx.fillText(line, lineDrawX, lineY);
    });
    
    // 绘制下划线（Canvas 原生不支持，需要手动绘制）
    if (config.underline) {
      ctx.strokeStyle = config.fontColor || '#000000';
      ctx.lineWidth = 1;
      
      // 为每一行文字绘制下划线
      displayLines.forEach((line, index) => {
        if (line) {
          const lineWidth = ctx.measureText(line).width;
          const underlineY = text.y + (index + 1) * lineHeight - 4; // 每行文字下方2px
          
          ctx.beginPath();
          
          // 计算每行下划线的位置
          let underlineStartX = text.x;
          let underlineEndX = text.x + lineWidth;
          
          if (textAlign === 'center') {
            // 居中对齐时，下划线也居中
            underlineStartX = text.x + textWidth / 2 - lineWidth / 2;
            underlineEndX = text.x + textWidth / 2 + lineWidth / 2;
          } else if (textAlign === 'right') {
            // 右对齐
            underlineStartX = text.x + textWidth - lineWidth;
            underlineEndX = text.x + textWidth;
          }
          
          // 确保下划线不超出区块边界
          underlineStartX = Math.max(text.x, underlineStartX);
          underlineEndX = Math.min(text.x + textWidth, underlineEndX);
          
          ctx.moveTo(underlineStartX, underlineY);
          ctx.lineTo(underlineEndX, underlineY);
          ctx.stroke();
        }
      });
    }
    
    // 绘制悬浮边框和调节手柄
    if (hoveredTextId.value === text.id) {
      const fontSize = config.fontSize || 16;
      const textWidth = config.textWidth === 0 ? canvasRect.value.width / 2 : (config.textWidth || 200);
      const textHeight = config.textHeight === 0 ? (fontSize + 8) * 2 : (config.textHeight || (fontSize + 8) * 2);
      
      // 绘制虚线边框
      ctx.strokeStyle = '#007AFF';
      ctx.lineWidth = 1;
      ctx.setLineDash([5, 5]);
      ctx.strokeRect(text.x, text.y - 5, textWidth, textHeight + 10);
      ctx.setLineDash([]);
      
      // 绘制右下角调节手柄
      ctx.fillStyle = '#007aff00';
      ctx.fillRect(text.x + textWidth - 8, text.y + textHeight - 8, 16, 16);
    }
  });
}

// 绘制对齐线
function drawAlignmentLines(ctx: CanvasRenderingContext2D) {
  if (!showCenterLines.value && !showAlignmentLines.value) return;

  ctx.strokeStyle = '#007AFF';
  ctx.lineWidth = 1;
  ctx.setLineDash([5, 5]);

  // 绘制中心线
  if (showCenterLines.value) {
    const center = centerLines.value;
    ctx.beginPath();
    ctx.moveTo(center.x, 0);
    ctx.lineTo(center.x, canvasRect.value.height);
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(0, center.y);
    ctx.lineTo(canvasRect.value.width, center.y);
    ctx.stroke();
  }

  // 绘制对齐线
  if (showAlignmentLines.value && alignmentLine.value.type) {
    const line = alignmentLine.value;
    ctx.beginPath();
    if (line.type === 'vertical') {
      ctx.moveTo(line.x, 0);
      ctx.lineTo(line.x, canvasRect.value.height);
    } else {
      ctx.moveTo(0, line.y);
      ctx.lineTo(canvasRect.value.width, line.y);
    }
    ctx.stroke();
  }

  ctx.setLineDash([]);
}

function drawCanvas() {
  if (canvasRef.value && backgroundImage.value) {
    const canvas = canvasRef.value;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;

    // 获取设备像素比
    const devicePixelRatio = window.devicePixelRatio || 1;

    // 获取canvas的显示尺寸
    const rect = canvas.getBoundingClientRect();
    const displayWidth = rect.width;

    // 计算图片绘制参数
    const img = backgroundImage.value;
    const imgWidth = img.width;
    const imgHeight = img.height;

    // 图片宽度等于canvas宽度，高度按比例缩放
    const drawWidth = displayWidth;
    const drawHeight = (displayWidth / imgWidth) * imgHeight;

    // 更新canvas尺寸信息
    canvasRect.value = { width: displayWidth, height: drawHeight };

    // 设置canvas的实际尺寸（考虑设备像素比）
    canvas.width = displayWidth * devicePixelRatio;
    canvas.height = drawHeight * devicePixelRatio;

    // 缩放绘图上下文以匹配设备像素比
    ctx.scale(devicePixelRatio, devicePixelRatio);

    // 清空画布
    ctx.clearRect(0, 0, displayWidth, drawHeight);

    // 绘制图片
    ctx.drawImage(img, 0, 0, drawWidth, drawHeight);

    // 绘制文案区块
    drawTextBlocks(ctx);

    // 绘制对齐线
    drawAlignmentLines(ctx);
  }
}

// 鼠标事件处理
function handleMouseDown(e: MouseEvent) {
  if (!props.edit) return;
  const canvas = canvasRef.value;
  if (!canvas) return;

  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;

  // 检查是否点击了调节手柄
  const resizingText = textBlocks.value.find(text => {
    const config = text.textFormatConfigs || {};
    const fontSize = config.fontSize || 16;
    const textWidth = config.textWidth === 0 ? canvasRect.value.width / 2 : (config.textWidth || 200);
    const textHeight = config.textHeight === 0 ? (fontSize + 8) * 2 : (config.textHeight || (fontSize + 8) * 2);
    return x >= text.x + textWidth - 8 && x <= text.x + textWidth + 8 &&
           y >= text.y + textHeight - 8 && y <= text.y + textHeight + 8;
  });

  if (resizingText) {
    isResizing.value = true;
    resizingTextId.value = resizingText.id;
    resizeStartPos.value = { x, y };
    const config = resizingText.textFormatConfigs || {};
    const fontSize = config.fontSize || 16;
    resizeStartSize.value = {
      width: config.textWidth === 0 ? canvasRect.value.width / 2 : (config.textWidth || 200),
      height: config.textHeight === 0 ? (fontSize + 8) * 2 : (config.textHeight || (fontSize + 8) * 2)
    };
    return;
  }

  // 检查是否点击了文案区块
  const clickedText = textBlocks.value.find(text => {
    const config = text.textFormatConfigs || {};
    const fontSize = config.fontSize || 16;
    const textWidth = config.textWidth === 0 ? canvasRect.value.width / 2 : (config.textWidth || 200);
    const textHeight = config.textHeight === 0 ? (fontSize + 8) * 2 : (config.textHeight || (fontSize + 8) * 2);
    return x >= text.x && x <= text.x + textWidth &&
      y >= text.y && y <= text.y + textHeight;
  });

  if (clickedText) {
    isDragging.value = true;
    draggedTextId.value = clickedText.id;
    dragStartPos.value = { x: x - clickedText.x, y: y - clickedText.y };
  }
}

function handleMouseMove(e: MouseEvent) {
  if (!props.edit) return;
  const canvas = canvasRef.value;
  if (!canvas) return;

  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;

  // 检测悬浮状态和鼠标样式
  let foundHovered = false;
  let isOverResizeHandle = false;
  
  textBlocks.value.forEach(text => {
    const config = text.textFormatConfigs || {};
    const fontSize = config.fontSize || 16;
    const textWidth = config.textWidth === 0 ? canvasRect.value.width / 2 : (config.textWidth || 200);
    const textHeight = config.textHeight === 0 ? (fontSize + 8) * 2 : (config.textHeight || (fontSize + 8) * 2);
    
    // 检查是否在文案区块内
    if (x >= text.x && x <= text.x + textWidth &&
        y >= text.y && y <= text.y + textHeight) {
      hoveredTextId.value = text.id;
      foundHovered = true;
      
      // 检查是否在调节手柄区域
      if (x >= text.x + textWidth - 8 && x <= text.x + textWidth + 8 &&
          y >= text.y + textHeight - 8 && y <= text.y + textHeight + 8) {
        isOverResizeHandle = true;
      }
    }
  });
  
  if (!foundHovered) {
    hoveredTextId.value = null;
  }
  
  // 更新鼠标样式
  if (canvas) {
    if (isOverResizeHandle) {
      canvas.style.cursor = 'nw-resize';
    } else if (foundHovered) {
      canvas.style.cursor = 'move';
    } else {
      canvas.style.cursor = 'default';
    }
  }
  
  // 重新绘制canvas以更新边框显示状态
  drawCanvas();

  // 处理宽高拖拽
  if (isResizing.value && resizingTextId.value) {
    const deltaX = x - resizeStartPos.value.x;
    const deltaY = y - resizeStartPos.value.y;
    
    const newWidth = Math.max(50, resizeStartSize.value.width + deltaX);
    const newHeight = Math.max(20, resizeStartSize.value.height + deltaY);
    
    const textIndex = textBlocks.value.findIndex(t => t.id === resizingTextId.value);
    if (textIndex !== -1 && textBlocks.value[textIndex]) {
      if (!textBlocks.value[textIndex].textFormatConfigs) {
        textBlocks.value[textIndex].textFormatConfigs = {};
      }
      textBlocks.value[textIndex].textFormatConfigs.textWidth = newWidth;
      textBlocks.value[textIndex].textFormatConfigs.textHeight = newHeight;
      
      // 触发更新事件
      emit('update:banner', { ...props.banner, textConfigs: [...textBlocks.value] });
      
      // 重新绘制
      drawCanvas();
    }
    return;
  }

  // 处理位置拖拽
  if (!isDragging.value || !draggedTextId.value) return;

  // 计算实际位置
  let actualX = x - dragStartPos.value.x;
  let actualY = y - dragStartPos.value.y;

  // 检查是否靠近中心线
  const nearCenter = isNearCenterLine(actualX, actualY);
  showCenterLines.value = nearCenter.nearVertical || nearCenter.nearHorizontal;

  // 检查是否与其他文案对齐
  const alignment = findAlignmentLines(actualX, actualY, draggedTextId.value);
  showAlignmentLines.value = !!alignment;
  if (alignment) {
    alignmentLine.value = alignment;
  }

  // 吸附对齐
  const center = centerLines.value;
  if (nearCenter.nearVertical && center) {
    actualX = center.x;
  }
  if (nearCenter.nearHorizontal && center) {
    actualY = center.y;
  }

  if (alignment) {
    const snapped = snapToAlignment(actualX, actualY, alignment);
    actualX = snapped.x;
    actualY = snapped.y;
  }

  // 更新文案位置
  const textIndex = textBlocks.value.findIndex(t => t.id === draggedTextId.value);
  if (textIndex !== -1 && draggedTextId.value && textBlocks.value[textIndex]) {
    textBlocks.value[textIndex].x = actualX;
    textBlocks.value[textIndex].y = actualY;

    // 触发更新事件
    emit('update:banner', { ...props.banner, textConfigs: [...textBlocks.value] });

    // 重新绘制
    drawCanvas();
  }
}

function handleMouseUp() {
  if (!props.edit) return;
  if (isDragging.value) {
    isDragging.value = false;
    draggedTextId.value = null;
    showCenterLines.value = false;
    showAlignmentLines.value = false;
    alignmentLine.value = { x: 0, y: 0, type: '' };
  }
  
  if (isResizing.value) {
    isResizing.value = false;
    resizingTextId.value = null;
  }
}

function handleMouseLeave() {
  if (!props.edit) return;
  handleMouseUp();
  hoveredTextId.value = null;
  
  // 重置鼠标样式
  const canvas = canvasRef.value;
  if (canvas) {
    canvas.style.cursor = 'default';
  }
  
  // 重新绘制canvas以清除边框
  drawCanvas();
}

// 监听文案配置变化
watch(() => props.banner.textConfigs, (newConfigs) => {
  if (!newConfigs) return;
  textBlocks.value = [...newConfigs];
  if (imgLoaded.value) {
    drawCanvas();
  }
}, { deep: true, immediate: true });

watch(() => props.banner.bannerUrl, (newVal, oldVal) => {
  if (!newVal) return;
  // 只有当 bannerUrl 真正发生变化时才重新加载图片
  if (newVal !== oldVal) {
    loadImage(newVal);
  }
}, { deep: true });

// 监听窗口大小变化，重新绘制canvas
watch(() => imgLoaded.value, (loaded) => {
  if (loaded) {
    // 添加窗口大小变化监听器
    const handleResize = () => {
      if (imgLoaded.value) {
        drawCanvas();
      }
    };

    window.addEventListener('resize', handleResize);

    // 清理监听器
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }
});

onUnmounted(() => {
  imgLoaded.value = false
  console.log(props.banner.bannerUrl)
});

</script>
<template>
  <div v-loading="imgLoading" class="w-full min-h-[100px] h-auto relative">
    <canvas v-if="imgLoaded" ref="canvasRef" class="w-full object-contain cursor-pointer" id="canvasView" @mousedown="handleMouseDown"
      @mousemove="handleMouseMove" @mouseup="handleMouseUp" @mouseleave="handleMouseLeave"></canvas>
  </div>
</template>
<style lang="scss" scoped></style>
